import lib from './ThreeLib.js'
import { Color } from '../js/three.module.js';

const defAttr = () => ({
    gl: null,
    arr: [],
    list: [],
    // { name : 'a_Position', size : 3, beginIndex : 0 }
    texture: {},
    // 'u_Sampler' : {
    //      image,
    //      WRAP_W,
    //      WRAP_H,
    //      MIN_FILTER,
    //      MAG_FILTER,
    //      format = gl.RGB,
    //      flipY = 1,
    //}
    uniforms: {},
    // 'uniforms' : {
    //      u_Set :{
    //          type : 'uniform1f',
    //          value: 0.0
    //      }
    //
    //}
    elementBytes: 4,
    eachCount: 0,
    types: [
        "POINTS",
        "TRIANGLES", "TRIANGLE_STRIP", "TRIANGLE_FAN",
        "LINES", "LINE_STRIP", "LINE_LOOP",
    ],
    nodeCount: 0,
})

export default class Poly {
    constructor(attr) {
        Object.assign(this, defAttr(), attr);
        this.init();
    }

    init() {
        const { gl, arr, list } = this;
        if (!gl) {
            return;
        }
        //绑定缓冲对象
        gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
        //写入数据
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arr), gl.STATIC_DRAW);

        this.eachCount = list[list.length - 1].beginIndex + list[list.length - 1].size;

        this.updateAttribute();

        this.updateUniform();

        this.updateNodeCount();
    }

    updateAttribute() {
        const { gl, list, elementBytes } = this;
        list.forEach(u => {
            let obj = gl.getAttribLocation(gl.program, u.name);
            gl.vertexAttribPointer(obj, u.size, gl.FLOAT, false, this.eachCount * elementBytes, u.beginIndex * elementBytes);
            gl.enableVertexAttribArray(obj);
        });
    }

    updateTexture() {
        const { gl, texture } = this;

        Object.entries(texture).forEach(([key, value], index) => {
            const {
                image,
                WRAP_H,
                WRAP_W,
                MIN_FILTER = gl.LINEAR,
                MAG_FILTER,
                format = gl.RGB,
                flipY = 1,
            } = value;

            //是否反转Y轴
            flipY && gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);

            // 激活纹理单元
            gl.activeTexture(gl[`TEXTURE${index}`]);
            gl.bindTexture(gl.TEXTURE_2D, gl.createTexture());

            gl.texImage2D(
                gl.TEXTURE_2D,
                0,
                format,
                format,
                gl.UNSIGNED_BYTE,
                image
            );

            //设置非二次幂图片(非二次幂图片只有在边缘加紧时才可以显示)
            WRAP_H && gl.texParameteri(
                gl.TEXTURE_2D,//二维纹理
                gl.TEXTURE_WRAP_T,//纹理容器在t方向的尺寸
                gl.CLAMP_TO_EDGE//边缘加紧的意思
            );
            WRAP_W && gl.texParameteri(
                gl.TEXTURE_2D,//二维纹理
                gl.TEXTURE_WRAP_S,//纹理容器在s方向的尺寸
                gl.CLAMP_TO_EDGE//边缘加紧的意思
            );

            MAG_FILTER && gl.texParameteri(
                gl.TEXTURE_2D,//二维纹理
                gl.TEXTURE_MAG_FILTER,//纹理缩小滤波器(当图片源比显示框大的时候进行等比缩小)
                gl.MAG_FILTER//线性
            );

            if (!MIN_FILTER || MIN_FILTER > 9729) {
                gl.generateMipmap(gl.TEXTURE_2D)
            }

            MIN_FILTER && gl.texParameteri(
                gl.TEXTURE_2D,
                gl.TEXTURE_MIN_FILTER,
                MIN_FILTER
            )

            const u_Sampler = gl.getUniformLocation(gl.program, key);
            gl.uniform1i(u_Sampler, index);//gl.TEXTURE0激活的是0
        });


    }

    updateUniform() {
        const { gl, uniforms } = this;
        Object.entries(uniforms).forEach(([key, values], index) => {
            const { type, value } = values;
            let obj = gl.getUniformLocation(gl.program, key);
            if (type.includes('Matrix')) {
                gl[type](obj, false, value)
            } else {
                gl[type](obj, value)
            }
        });
    }

    updateNodeCount() {
        const { arr, eachCount } = this;
        this.nodeCount = arr.length / eachCount;
    }

    updateBuffer() {
        const { gl, arr } = this;
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arr), gl.STATIC_DRAW);
    }

    getArr() {
        return this.list;
    }

    draw(types = this.types) {
        const { gl, nodeCount } = this;
        // lib.clearCanvas(gl, new Color("rgba(255,255,255,1)"), 1);
        // lib.clearCanvas(gl, new Color("rgba(0,0,0,1)"), 1);
        for (let type of types) {
            gl.drawArrays(gl[type], 0, nodeCount);
            // gl.drawArrays(gl[type], 0, 640);
        }
    }
}